//////////////////////////////////////////////////////
//  这里实现标签页的切换
//////////////////////////////////////////////////////

function initSwitchTab() {
    // 1. 先获取到具体相关的元素(标签页的元素, 会话列表, 好友列表)
    let tabSession = document.querySelector('.tab .tab-session');
    let tabFriend = document.querySelector('.tab .tab-friend');
    //   querySelectorAll 可以同时选中多个元素, 得到的结果是个数组
    //   [0] 就是会话列表
    //   [1] 就是好友列表

    let lists = document.querySelectorAll('.list');
    // 2. 针对标签页按钮, 注册点击事件
    // 如果是点击 会话标签 按钮, 就会把会话标签的背景图片进行设置
    // 同时把会话列表显示出来, 把好友列表隐藏
    // 如果点击的是 好友列表标签按钮, 就把好友按钮的背景图片进行设置
    // 同时把好友列表显示出来 把会话列表隐藏

    tabSession.onclick = function () {
        // a. 设置图标
        tabSession.style.backgroundImage = 'url(img/对话.png)';
        tabFriend.style.backgroundImage = 'url(img/用户2.png)';
        lists[0].classList = 'list';
        lists[1].classList = 'list hide';
    }

    tabFriend.onclick = function () {
        // a.设置图标
        tabSession.style.backgroundImage = 'url(img/对话2.png)';
        tabFriend.style.backgroundImage = 'url(img/用户.png)';

        lists[1].classList = 'list';
        lists[0].classList = 'list hide';
    }

}

initSwitchTab();


// ///////////////////////////////////////
// 操作 webSocket
/////////////////////////////////////////

//创建 webSocket 实例
// let webSocket = new WebSocket("ws://127.0.0.1:8080/WebSocketMessage");
let webSocket = new WebSocket("ws://"+ location.host+"/WebSocketMessage");

webSocket.onopen = function () {
    console.log("webSocket 连接成功");
}

webSocket.onmessage = function (e) {
    console.log("webSocket 收到消息:" + e.data);
    // 此时收到的 e.data 是个 json 字符串, 需要转成 js 对象
    let resp = JSON.parse(e.data);
    if (resp.type == 'message') {
        //处理消息响应
        handleMessage(resp);
    } else {
        //resp的type 出错
        console.log("resp.type 不符合要求!");
    }

}

webSocket.onclose = function () {
    console.log("webSocket 连接关闭")
}

webSocket.onerror = function () {
    console.log("webSocket 连接异常")
}

function handleMessage(resp) {
    //把客户端收到的消息展示出来
    //展示到对应的会话预览器和主界面

    // 1.根据响应中的 sessionId 获取到对话中的li标签
    // 如果 li 标签不存在, 则创建一个新的
    let curSessionLi = findSessionLi(resp.sessionId);
    if (curSessionLi == null) {
        //就需要创建一个新的 li 标签标识新的会话
        curSessionLi = document.createElement('li');
        curSessionLi.setAttribute('message-session-id', resp.sessionId);
        // 此处的 p 标签内部应该放消息的预览内容, 一会后面统一完成, 这里先置空
        curSessionLi.innerHTML = '<h3>' + resp.fromName + '</h3>'
            + '<p></p>';
        //给 li 标签新增一个点击事件
        curSessionLi.onclick = function () {
            //这个写法能保证点击哪个 li 标签
            //此处对应的 clickSession 函数的参数就能拿到哪个 li 标签
            clickSession(curSessionLi);
        }
    }

    // 2.把新的消息显示到会话预览区域 ( li 标签里的 p 标签中)
    // 如果消息太长, 就需要进行截段
    let p = curSessionLi.querySelector('p');
    p.innerHTML = resp.content;
    if(p.innerHTML.length > 10) {
        p.innerHTML = p.innerHTML.substring(0,10) + '...';
    }

    // 3.把收到消息的会话, 放到会话列表的最上面
    let sessionListUL = document.querySelector('#session-list');
    sessionListUL.insertBefore(curSessionLi, sessionListUL.children[0]);

    // 4.如果当前收到消息的会话处于被选中状态, 则把当前消息给放到右侧消息例表中
    if(curSessionLi.className == 'selected') {
        // 把消息列表添加一个新的消息
        let messageShowDiv = document.querySelector('.right .message-show');
        addMessage(messageShowDiv, resp);
        // 新增消息的同时, 注意调整滚动条的位置, 保证新消息虽然在底部, 但是能让用户直接看到
        scrollBottom(messageShowDiv)
    }
    
    // 还可以在会话窗口上给个提示 (红色数组, 有几条消息未读) 还可以播放提示应
     

}

function findSessionLi(targetSessionId) {
    // 获取到所有的会话列表中的 li 标签
    let sessionLis = document.querySelectorAll('#session-list li');
    for (let li of sessionLis) {
        let sessionId = li.getAttribute('message-session-id');
        if (sessionId == targetSessionId) {
            return li;
        }
    }
    return null;
}
// ////////////////////////////////////////////
//  实现消息发送/接收逻辑
///////////////////////////////////////////////

function initSendButton() {
    //1.获取到发送按钮 和 消息输入框
    let sendButton = document.querySelector('.right .ctrl button');
    let messageInput = document.querySelector('.right .message-input');
    //2.给发送按钮注册一个点击事件
    sendButton.onclick = function () {
        // a.先针对输入框的内容做个简单判定. 比如输入框的内容为空, 则啥都不干
        console.log("点击: " + messageInput.value);
        if (!messageInput.value) {
            // value 的值是 null 或者 '' 都会触发这个条件
            return;
        }
        // b.获取当前选中的li标签的 sessionId
        let selectedLi = document.querySelector('#session-list .selected');
        if (selectedLi == null) {
            //当前没有 li 标签被选中
            return;
        }
        let sessionId = selectedLi.getAttribute('message-session-id');
        // c.构造 json 数据
        let req = {
            type: 'message',
            sessionId: sessionId,
            content: messageInput.value
        };
        req = JSON.stringify(req);
        console.log("[webSocket] send:" + req);
        // d.通过 webSocket 发送消息
        webSocket.send(req);
        // e.发送完成之后, 清空之前的输入框
        messageInput.value = '';
    }
}

initSendButton();


// ////////////////////////////////////////////
//  从服务器获取用户登录数据
///////////////////////////////////////////////

function getUserInfo() {
    $.ajax({
        type: 'get',
        url: 'userInfo',
        success: function (body) {
            //从服务器获取到数据
            //校验结果是否有效
            if (body.userId && body.userId > 0) {
                //如果结果有效, 则把用户名显示到页面上
                //同时也可以记录 userId 到html标签的属性上, 以备后用
                let userDiv = document.querySelector('.main .left .user');
                userDiv.innerHTML = body.username;
                userDiv.setAttribute("user-id", body.userId);
            } else {
                //如果结果无效,当前未登录 则跳转到登录页面
                alert("当前用户未登录");
                location.assign('login.html');
            }
        }
    });
}

getUserInfo();

function getFriendList() {
    $.ajax({
        type: 'get',
        url: 'friendList',
        success: function (body) {
            //1.先把之前的好友列表的内容清空
            let frinedListUL = document.querySelector('#friend-list');
            frinedListUL.innerHTML = '';
            //2.遍历body 把服务器响应的结果 加回到 friend-list 中
            for (let friend of body) {
                let li = document.createElement('li');
                li.innerHTML = '<h4>' + friend.friendName + '</h4>';
                //此处把 friendId 也都记录下来, 以备后用
                //把 friendId 作为一个html 的自定义属性, 加到 li 标签上就行了
                li.setAttribute('friend-id', friend.friendId);
                frinedListUL.appendChild(li);

                //每个li标签对应界面上的一个好友选项, 给这个li加上点击事件的处理
                li.onclick = function () {
                    //参数表示区分了当前用户点击的是哪个好友
                    clickFriend(friend);
                }

            }
        },
        error: function () {
            console.log("获取好友列表失败");
        }
    });
}

getFriendList();

function getSessionList() {
    $.ajax({
        type: 'get',
        url: 'sessionList',
        success: function (body) {
            //1.清空之前的会话列表
            let sessionListUrl = document.querySelector('#session-list');
            sessionListUrl.innerHTML = '';
            //2.遍历响应的数组, 针对结果来构造页面
            for (let session of body) {
                // 针对 lastMessage 的长度进行截断处理
                if (session.lastMessage.length > 10) {
                    session.lastMessage = session.lastMessage.substring(0, 10) + '...';
                }

                let li = document.createElement('li');
                // 吧会话id保存在 li 标签的自定义属性中
                li.setAttribute('message-session-id', session.sessionId);
                li.innerHTML = '<h3>' + session.friends[0].friendName + '</h3>'
                    + '<p>' + session.lastMessage + '</p>';

                sessionListUrl.appendChild(li);

                //给 li 标签新增一个点击事件
                li.onclick = function () {
                    //这个写法能保证点击哪个 li 标签
                    //此处对应的 clickSession 函数的参数就能拿到哪个 li 标签
                    clickSession(li);
                }
                // sessionListUrl.innerHTML=li;
            }
        }
    });
}

getSessionList();

function clickSession(currentLi) {
    //1.设置高亮
    let allLis = document.querySelectorAll('#session-list>li');
    activeSession(allLis, currentLi);
    //2.获取指定会话的历史消息
    let sessionId = currentLi.getAttribute("message-session-id");
    getHistoryMessage(sessionId);
}

function activeSession(allLis, currentLi) {
    // 这里的循环遍历, 更主要的目的是取消未被选择的 li 标签的 className
    for (let li of allLis) {
        if (li == currentLi) {
            li.className = 'selected';
        } else {
            li.className = '';
        }
    }
}

// 这个函数负责获取指定会话的历史消息
function getHistoryMessage(sessionId) {
    console.log("获取历史消息 sessionId = " + sessionId);
    //1.先清空右侧列表的已有内容
    let titleDiv = document.querySelector('.right .title');
    titleDiv.innerHTML = '';

    let messageShowDiv = document.querySelector('.right .message-show');
    messageShowDiv.innerHTML = '';

    //2.重新设置会话的标题 新的会话标题是点击的那个会话上面显示的标题
    // 先找到当前选中的会话是哪个, 被选中的会话带有 selected 类的
    let selectedH3 = document.querySelector('#session-list .selected>h3');
    if (selectedH3) {
        //selectedH3可能不存在, 比如页面加载阶段, 可能并没有哪个会话被选中
        //也就没有会话带有 selected 标签, 此时就无法查询出 selectedH3
        titleDiv.innerHTML = selectedH3.innerHTML;
    }

    //3.发送 ajax 请求给服务器, 获取到会话的历史消息
    $.ajax({
        type: 'get',
        url: 'message?sessionId=' + sessionId,
        success: function (body) {
            // 此处返回的 body 是一个 js 对象数组 里面的每一个元素都是一条消息
            // 直接遍历即可
            for (let message of body) {
                addMessage(messageShowDiv, message);
            }
            //加个操作: 在构造好消息列表之后, 控制滚动条, 自动滚动到最下方
            scrollBottom(messageShowDiv);
        }
    });
}

function addMessage(messageShowDiv, message) {
    let messageDiv = document.createElement('div');
    // 此处需要针对当前用户消息是不是用户自己发的, 决定是靠左还是靠右
    let selfUsername = document.querySelector('.main .left .user').innerHTML;
    if (selfUsername == message.fromName) {
        //消息是自己发的, 靠左
        messageDiv.className = 'message message-right';
    } else {
        //消息是别人发的, 靠左
        messageDiv.className = 'message message-left';
    }
    messageDiv.innerHTML = '<div class="box">'
        + '<h4>' + message.fromName +'</h4>'
        + '<p>' + message.content + '</p>'
        + '</div>';
    messageShowDiv.appendChild(messageDiv);
}

// 把messageShowDiv 里的内容滚动到底部
function scrollBottom(elem) {
    // 1.获取到可视区域的高度H
    let clientHeight = elem.offsetHeight;
    // 2.获取到内容的总高度
    let scrollHeight = elem.scrollHeight;
    // 3.进行滚动操作, 第一个参数是水平方向滚动的尺寸, 第二个参数是垂直方向滚动的尺寸
    elem.scrollTo(0, scrollHeight - clientHeight);
}


//点击好友列表项, 触发的函数
function clickFriend(friend) {
    // 1.先判定一下当前这个好友是否有对应的会话
    // 使用一个单独的函数来实现, 这个函数参数是用户的名字, 返回值是一个 li 标签, 找到了就是返回会话列表里的li, 如果没有找到, 返回 null
    let sessionLi = findSessionByName(friend.friendName);
    let sessionListUL = document.querySelector('#session-list');
    if (sessionLi) {
        // 2.如果存在匹配的结果, 就把这个会话设置为选中状态,获取历史消息 并且置顶
        // insertBefore 吧这个找到的 li 标签放到最前面
        sessionListUL.insertBefore(sessionLi, sessionListUL.children[0]);
        // 此处设置会话的选中状态, 获取历史消息, 
        // 直接调用clickSession(sessionLi);
        //或者还可以模拟一下点击操作
        sessionLi.click();

    } else {
        // 3.如果不存在匹配的结果, 就创建个新的会话 (创建 li 标签 + 通知服务器)
        sessionLi = document.createElement('li');
        // 构造 li 标签内容, 由于新会话没有 "最后一条消息", p 标签内容就设为空即可
        sessionLi.innerHTML = '<h3>' + friend.friendName + '</h3>' + '<p></p>';

        // 把标签进行置顶
        sessionListUL.insertBefore(sessionLi, sessionListUL.children[0]);
        //新增加的 li 标签没有点击事件, 需要增加
        sessionLi.onclick = function () {
            clickSession(sessionLi);
        }
        sessionLi.click();
        // 发送消息给服务器, 告诉服务器当前新创建的会话是啥样的
        createSession(friend.friendId, sessionLi);
    }

    //4.还需要把标签页给切换到会话列表
    // 实现方式很容易, 只要找到会话标签页按钮, 模拟一个点击操作即可
    let tabSession = document.querySelector('.tab .tab-session');
    tabSession.click();
}


function findSessionByName(username) {
    //先获取到会话列表中所有的 li 标签
    //一次遍历, 看看这些 li 标签谁的名字和要查找的名字一致
    let sessionLis = document.querySelectorAll('#session-list>li');
    for (let sessionLi of sessionLis) {
        // 获取到该 li 标签里的 h3 标签, 进一步得到名字
        let h3 = sessionLi.querySelector('h3');
        if (h3.innerHTML == username) {
            return sessionLi;
        }
    }
    return null;
}

function createSession(friendId, sessionLi) {
    $.ajax({
        type: 'post',
        url: 'session?toUserId=' + friendId,
        success: function (body) {
            console.log("会话创建成功! sessionId = " + body.sessionId);
            sessionLi.setAttribute('message-session-id', body.sessionId);
        },
        error: function () {
            console.log("会话创建失败!");
        }
    });
}

